package main

import (
	"fmt"
)

type Books struct {
	book_id int
	name    string
	price   float64
}

func main() {
	fmt.Println("<<<< 关于值传递和引用传递的实验：普通类型 vs 结构体/切片/Map >>>>")

	// 只有引用传递中值会被修改
	fmt.Println("--Struct-值传递测试--")
	book1 := Books{1, "Go语言测试", 100.25}
	fmt.Printf("Book Name :%v, Price: %v \n", book1.name, book1.price)
	testVal(book1)
	fmt.Printf("Book Name :%v, Price: %v \n", book1.name, book1.price)

	fmt.Println("--Struct-引用传递测试--")
	book2 := Books{2, "Go语言测试2", 110.25}
	fmt.Printf("Book Name :%v, Price: %v \n", book2.name, book2.price)
	testRef(&book2)
	fmt.Printf("Book Name :%v, Price: %v \n", book2.name, book2.price)

	fmt.Println()

	// 只有引用传递中值会被修改 (注意与下面的Slice区分)
	fmt.Println("--Array-值传递测试--")
	ary1 := [3]int{1, 2, 3}
	fmt.Printf("Array1[1] :%v \n", ary1[1])
	testArrayVal(ary1)
	fmt.Printf("Array1[1] :%v \n", ary1[1])

	fmt.Println("--Array-引用传递测试--")
	ary2 := [3]int{4, 5, 6}
	fmt.Printf("Array2[1] :%v \n", ary2[1])
	testArrayRef(&ary2)
	fmt.Printf("Array2[1] :%v \n", ary2[1])

	fmt.Println()

	// 无论是值传递还是引用传递，切片中的值都会被修改
	fmt.Println("--Slice-值传递测试--")
	slice1 := []int{1, 2, 3}
	fmt.Printf("Slice1[1] :%v \n", slice1[1])
	testSliceVal(slice1)
	fmt.Printf("Slice1[1] :%v \n", slice1[1])

	fmt.Println("--Slice-引用传递测试--")
	slice2 := []int{4, 5, 6}
	fmt.Printf("Slice2[1] :%v \n", slice2[1])
	testSliceRef(&slice2)
	fmt.Printf("Slice2[1] :%v \n", slice2[1])

	fmt.Println()

	// 无论是值传递还是引用传递，Map中的值都会被修改
	m1 := map[string]int{
		"apple":  1,
		"banana": 2,
		"orange": 3,
	}
	fmt.Printf("banana1 :%v \n", m1["banana"])
	testMapVal(m1)
	fmt.Printf("banana1 :%v \n", m1["banana"])

	m2 := map[string]int{
		"apple":  1,
		"banana": 2,
		"orange": 3,
	}
	fmt.Printf("banana2 :%v \n", m2["banana"])
	testMapRef(&m2)
	fmt.Printf("banana2 :%v \n", m2["banana"])

}

func testVal(book Books) {
	book.price = 125.25
}

func testRef(book *Books) {
	book.price = 135.25
}

func testArrayVal(ary [3]int) {
	ary[1] = 10
}

func testArrayRef(ary *[3]int) {
	(*ary)[1] = 11
}

func testSliceVal(slice []int) {
	slice[1] = 10
}

func testSliceRef(slice *[]int) {
	(*slice)[1] = 11
}

func testMapVal(m map[string]int) {
	m["banana"] = 10
}

func testMapRef(m *map[string]int) {
	(*m)["banana"] = 11
}
